Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Apply the UARTE workaround for nrf91 and nrf53 #319

Merged
merged 8 commits into from
May 14, 2021
Merged

Apply the UARTE workaround for nrf91 and nrf53 #319

merged 8 commits into from
May 14, 2021

Conversation

jonathanpallant
Copy link
Member

See ttps://github.com/NordicSemiconductor/nrfx/blob/master/drivers/src/nrfx_uarte.c#L197

Jonathan Pallant (42 Technology) added 2 commits May 14, 2021 16:28
It seems like endtx and txstopped race, and if we see txstopped first
we return an error, causing writeln!(...).unwrap() to panic.

This changes makes the UART work reliably on the nRF9160-PDK.
@jonathanpallant
Copy link
Member Author

This also removes the check for txstopped, which doesn't work on the nrf9160 (the event is always set).

@@ -43,6 +43,16 @@ where
T: Instance,
{
pub fn new(uarte: T, mut pins: Pins, parity: Parity, baudrate: Baudrate) -> Self {
// Is the UART already on? It might be if you had a bootloader
if uarte.enable.read().bits() != 0 {
while uarte.events_txstopped.read().bits() == 0 {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

events_txstopped only fires if whoever was using it before did a stoptx. This might spin forever if that's not the case.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is exactly why the errata workaround checks for rxenable/txenable, but we can't rely on those being present in nrf52 since they're undocuemnted...

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, I see. With no check, I splatter the last line emitted by SPM. What's a good thing to check for here? Or do we not care that we configure the UART whilst it may still be enabled?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

there might be side effects if it's not disabled yeah :S

Maybe always do a stoptx? I think if tx is stopped stoptx still causes a new txstopped, so the loop is guaranteed to hang? I'm not 100% sure though

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, will do.

if endtx || txstopped {
break;
}
while self.0.events_endtx.read().bits() == 0 {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the events_txstopped.reset(); above is no longer needed.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Noted. Will remove.

}

// Conservative compiler fence to prevent optimizations that do not
// take in to account actions by DMA. The fence has been placed here,
// after all possible DMA actions have completed.
compiler_fence(SeqCst);

if txstopped {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe remove the Transmit error? it'd be a breaking change though.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From the enum? Might as well leave it in for now in case we do need it again.

// Lower power consumption by disabling the transmitter once we're
// finished.
self.0.tasks_stoptx.write(|w|
// `1` is a valid value to write to task registers.
unsafe { w.bits(1) });

// Wait for transmitter to stop.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The tasks_stoptx write and this spin is unneeded. If you don't abort a tx, just receiving endtx already means the tx machinery is fully stopped.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

According to Nordic:

            // Transmitter has to be stopped by triggering the STOPTX task to achieve
            // the lowest possible level of the UARTE power consumption.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not that we seem to care about power consumption (as we busy-wait during a DMA transmit to the UART)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh huh, strange. When I experimented with this, I saw UARTE using power as long as it's enabled, no matter what the tx/rx state is, so to have low power you have to disable it anyway... Embassy only waits for txstopped when disabling it, and only if the tx was aborted, which seems to work fine.

Seeing nordic has this code I'm now OK with leaving this in, though I don't fully get what the purpose is.

@@ -109,7 +181,6 @@ where

// Reset the events.
self.0.events_endtx.reset();
self.0.events_txstopped.reset();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oops. Actually this was needed if we keep the blocking wait for txstopped below 😅 ... It should probably be moved next to that so it's more obvious why it's needed.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤣

Copy link
Member

@Dirbaio Dirbaio left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks great

bors r+

@bors
Copy link
Contributor

bors bot commented May 14, 2021

Build succeeded:

@bors bors bot merged commit 39c0b8f into master May 14, 2021
@bors bors bot deleted the uart-fixes branch May 14, 2021 17:45
@huntc huntc mentioned this pull request May 15, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants